import 'package:azring/common/res/assets.dart';
import 'package:azring/pages/sleep/sleep_logic.dart';
import 'package:azring/pages/sleep/sleep_state.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:getx_scaffold/getx_scaffold.dart';
import '../../core/controllers/ring_controller.dart';
import '../../common/styles/theme_manager.dart';
import '../../widgets/fixed_header_with_tabs.dart';
import '../status/calendar/simple_calendar_view.dart';

/// 时间范围枚举
enum TimeRange { day, week, month }

/// 睡眠页面
class SleepView extends StatefulWidget {
  final bool showBackButton; // 是否显示返回按钮
  
  const SleepView({
    super.key,
    this.showBackButton = false, // 默认不显示（作为tab页面）
  });

  @override
  State<SleepView> createState() => _SleepViewState();
}

class _SleepViewState extends State<SleepView> {
  // 获取睡眠控制器
  SleepLogic get controller => Get.find<SleepLogic>();

  // 获取戒指控制器
  RingController get ringLogic => Get.find<RingController>();

  // 当前选择的时间范围
  TimeRange currentTimeRange = TimeRange.day;

  @override
  void initState() {
    super.initState();
    // 数据加载已在 SleepLogic.initializeSleepData() 中处理，无需重复调用
  }

  /// 显示小睡说明弹窗
  void _showNapExplanationDialog() {
    Get.dialog(
      Dialog(
        backgroundColor: const Color(0xFF9E9E9E),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(24.r),
        ),
        child: Container(
          width: 340.w,
          padding: EdgeInsets.all(24.w),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // 标题
              Text(
                '关于小睡',
                style: TextStyle(
                  fontSize: 20.sp,
                  fontWeight: FontWeight.w600,
                  color: Colors.white,
                ),
              ),
              SizedBox(height: 16.h),
              // 图例 - 两个在一排
              Row(
                children: [
                  // 科学补觉区间范围（虚线框）
                  Expanded(
                    child: Column(
                      children: [
                        Container(
                          width: 60.w,
                          height: 20.h,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(10.r),
                            border: Border.all(
                              color: const Color(0xFF2F7BFF),
                              width: 2,
                              style: BorderStyle.solid,
                            ),
                          ),
                        ),
                        SizedBox(height: 8.h),
                        Text(
                          '科学补觉区间范围',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            fontSize: 12.sp,
                            color: Colors.white,
                          ),
                        ),
                      ],
                    ),
                  ),
                  SizedBox(width: 16.w),
                  // 实际小睡时间范围（实心橙色）
                  Expanded(
                    child: Column(
                      children: [
                        Container(
                          width: 60.w,
                          height: 20.h,
                          decoration: BoxDecoration(
                            color: const Color(0xFFE76234),
                            borderRadius: BorderRadius.circular(10.r),
                          ),
                        ),
                        SizedBox(height: 8.h),
                        Text(
                          '实际小睡时间范围',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            fontSize: 12.sp,
                            color: Colors.white,
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
              SizedBox(height: 20.h),
              // 说明文字
              Text(
                '小睡最佳时间段：午后1点至3点',
                style: TextStyle(
                  fontSize: 14.sp,
                  fontWeight: FontWeight.w600,
                  color: Colors.white,
                ),
              ),
              SizedBox(height: 8.h),
              Text(
                '这个时间窗口被称为"午后倦怠期"，是人体生物钟自然安排的第二个睡眠需求高峰（第一个在深夜）。选择在这个时间段小睡，是顺应生理节律，效果事半功倍。',
                style: TextStyle(
                  fontSize: 12.sp,
                  color: Colors.white.withOpacity(0.9),
                  height: 1.5,
                ),
              ),
              SizedBox(height: 16.h),
              // 设定时长
              Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Icon(
                    Icons.access_time,
                    color: const Color(0xFFE76234),
                    size: 18.sp,
                  ),
                  SizedBox(width: 8.w),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          '设定时长',
                          style: TextStyle(
                            fontSize: 14.sp,
                            fontWeight: FontWeight.w600,
                            color: Colors.white,
                          ),
                        ),
                        SizedBox(height: 4.h),
                        Text(
                          '• 首选20分钟：用于快速提神，无副作用。',
                          style: TextStyle(
                            fontSize: 12.sp,
                            color: Colors.white.withOpacity(0.9),
                            height: 1.5,
                          ),
                        ),
                        Text(
                          '• 可选90分钟：用于周末深度修复。',
                          style: TextStyle(
                            fontSize: 12.sp,
                            color: Colors.white.withOpacity(0.9),
                            height: 1.5,
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
              SizedBox(height: 12.h),
              // 避开陷阱
              Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Icon(
                    Icons.cancel,
                    color: const Color(0xFFE76234),
                    size: 18.sp,
                  ),
                  SizedBox(width: 8.w),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          '避开陷阱：',
                          style: TextStyle(
                            fontSize: 14.sp,
                            fontWeight: FontWeight.w600,
                            color: Colors.white,
                          ),
                        ),
                        SizedBox(height: 4.h),
                        Text(
                          '坚决避免在下午3点后长时间小睡。',
                          style: TextStyle(
                            fontSize: 12.sp,
                            color: Colors.white.withOpacity(0.9),
                            height: 1.5,
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildView() {
    return SafeArea(
      child: Column(
        children: [
          // 固定的头部（标题 + 日周月切换）
          FixedHeaderWithTabs(
            title: '睡眠',
            selectedIndex: _getSelectedIndex(),
            showBackButton: widget.showBackButton, // 根据参数控制返回按钮显示
            onTabChanged: (index) {
              setState(() {
                switch (index) {
                  case 0:
                    currentTimeRange = TimeRange.day;
                    break;
                  case 1:
                    currentTimeRange = TimeRange.week;
                    break;
                  case 2:
                    currentTimeRange = TimeRange.month;
                    break;
                }
                // 切换tab时重新加载对应类型的数据
                controller.loadSleepDataByType(_getTypeByTimeRange());
              });
            },
            actions: [
              IconButton(
                icon: Assets.status.calendar.image(
                  width: 22.w,
                  height: 22.w,
                  color: Colors.white.withValues(alpha: 0.9),
                ),
                onPressed: () async {
                  final selectedDate = await Get.to(() => const SimpleCalendarView(
                        calendarType: CalendarType.sleep,
                      ));
                  if (selectedDate != null && selectedDate is String) {
                    controller.loadSleepDataByDate(selectedDate);
                  }
                },
              ),
            ],
          ),
          // 可滚动的内容区域
          Expanded(
            child: SingleChildScrollView(
              child: Stack(
                children: [
                  // 顶部渐变背景
                  Positioned(
                    top: 0,
                    left: 0,
                    right: 0,
                    height: 300.h,
                    child: Container(
                      decoration: BoxDecoration(
                        gradient: LinearGradient(
                          begin: Alignment.topRight,
                          end: Alignment.bottomRight,
                          colors: ThemeManager.to.backgroundGradientColors,
                          stops: const [0.1, 0.3, 0.7, 1.0],
                        ),
                      ),
                    ),
                  ),
                  // 内容区域
                  Padding(
                    padding: EdgeInsets.symmetric(horizontal: 11.w, vertical: 20.h),
                    child: Column(
                      children: [
                        SizedBox(height: 20.h),
                  _buildSummaryHeader(),
                  SizedBox(height: 24.h),
                  _buildSleepChart(),
                  SizedBox(height: 32.h),
                  Obx(() {
                    // 从 API 数据获取 sleepValue
                    final qualityData = controller.state.sleepQualityData.value;
                    final sleepValue = qualityData?.sleepValue ?? '';
                    
                    return buildSectionCard(
                      title: '睡眠质量评分',
                      titleSuffix: sleepValue.isNotEmpty ? Container(
                        padding:
                            EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
                        decoration: BoxDecoration(
                          color: const Color(0xFF00C08B),
                          borderRadius: BorderRadius.circular(12.r),
                        ),
                        child: Text(sleepValue,
                            style: TextStyle(
                                fontSize: 12.sp,
                                color: Colors.white,
                                fontWeight: FontWeight.w700)),
                      ) : null,
                      child: _buildSleepDetails(inner: true),
                      onHelpTap: () => Toast.show('睡眠质量评分说明'),
                    );
                  }),
                  SizedBox(height: 20.h),
                  buildSectionCard(
                    title: '睡眠比例',
                    child: _buildSleepRatioSection(),
                  ),
                  SizedBox(height: 20.h),
                  buildSectionCard(
                    title: '小睡',
                    child: _buildNapSection(),
                    onHelpTap: () => _showNapExplanationDialog(),
                  ),
                  SizedBox(height: 20.h),
                  buildSectionCard(
                    title: '平均睡眠心率',
                    child: _buildAvgSleepHeartRateSection(),
                    onHelpTap: () => Toast.show('平均睡眠心率说明'),
                  ),
                  SizedBox(height: 20.h),
                  buildSectionCard(
                    title: '平均心率变异性',
                    child: _buildAvgHrvSection(),
                    onHelpTap: () => Toast.show('平均心率变异性说明'),
                  ),
                  SizedBox(height: 20.h),
                  buildSectionCard(
                    title: '血氧饱和度',
                    child: _buildBloodOxygenSection(),
                    onHelpTap: () => Toast.show('血氧饱和度说明'),
                  ),
                  SizedBox(height: 20.h),
                  buildSectionCard(
                    title: '睡眠活动状态',
                    child: _buildSleepActivitySection(),
                    onHelpTap: () => Toast.show('睡眠活动状态说明'),
                  ),
                  SizedBox(height: 20.h),
                        buildSectionCard(
                          title: '近7天睡眠趋势',
                          child: _buildActivityBarChart(),
                          onHelpTap: () => Toast.show('近7日睡眠趋势说明'),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  /// 获取当前选中的索引
  int _getSelectedIndex() {
    switch (currentTimeRange) {
      case TimeRange.day:
        return 0;
      case TimeRange.week:
        return 1;
      case TimeRange.month:
        return 2;
    }
  }

  /// 根据时间范围获取对应的type参数
  int _getTypeByTimeRange() {
    switch (currentTimeRange) {
      case TimeRange.day:
        return 1; // 日
      case TimeRange.week:
        return 2; // 周
      case TimeRange.month:
        return 3; // 月
    }
  }

  /// 通用分区卡片（圆角、描边、标题+问号、下方分割线）
  Widget buildSectionCard(
      {required String title,
      required Widget child,
      VoidCallback? onHelpTap,
      Widget? titleSuffix}) {
    return Container(
      decoration: BoxDecoration(
        color: const Color(0xff282528),
        borderRadius: BorderRadius.circular(20.r),
        border:
            Border.all(color: const Color.fromRGBO(33, 33, 33, 1), width: 1),
      ),
      child: Column(
        children: [
          Padding(
            padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.h),
            child: Row(
              children: [
                Text(
                  title,
                  style: TextStyle(
                    fontSize: 16.sp,
                    fontWeight: FontWeight.w600,
                    color: Colors.white,
                  ),
                ),
                if (titleSuffix != null) ...[
                  SizedBox(width: 8.w),
                  titleSuffix,
                ],
                const Spacer(),
                GestureDetector(
                  onTap: onHelpTap,
                  child: Icon(Icons.help_outline,
                      color: Colors.white.withOpacity(0.9), size: 18.sp),
                )
              ],
            ),
          ),
          Divider(
              height: 1,
              thickness: 1,
              color: const Color(0xff353235)),
          Padding(
            padding: EdgeInsets.all(12.w),
            child: child,
          )
        ],
      ),
    );
  }

  /// 总时长 + 日期 + 胶囊标签
  Widget _buildSummaryHeader() {
    return Obx(() {
      String totalDurationText;
      String dateText;
      String mainSleepText;
      String napSleepText;

      switch (currentTimeRange) {
        case TimeRange.day:
          // 优先使用 SleepLogic 的 state 数据（从 API 加载）
          totalDurationText =
              controller.state.dailySleepTime.value.replaceAll('分', '分钟');
          
          // 从 API 数据中获取主睡眠和小睡时长
          final sleepInfoData = controller.state.sleepInfoData.value;
          if (sleepInfoData != null) {
            mainSleepText = sleepInfoData.longSleepDuration ?? controller.state.dailySleepTime.value;
            napSleepText = sleepInfoData.shortSleepDuration ?? '0小时 0分';
          } else {
            mainSleepText = controller.state.dailySleepTime.value;
            napSleepText = '0小时 0分';
          }
          // 从 API 数据中获取日期，如果没有则使用当前日期
          if (sleepInfoData != null && sleepInfoData.dailyValue.isNotEmpty) {
            // 解析 API 返回的日期 "2025-10-14"
            try {
              final dateParts = sleepInfoData.dailyValue.split('-');
              if (dateParts.length == 3) {
                final year = int.parse(dateParts[0]);
                final month = int.parse(dateParts[1]);
                final day = int.parse(dateParts[2]);
                final date = DateTime(year, month, day);
                const List<String> weekNames = [
                  '周一',
                  '周二',
                  '周三',
                  '周四',
                  '周五',
                  '周六',
                  '周日'
                ];
                dateText =
                    '${year}年${month.toString().padLeft(2, '0')}月${day.toString().padLeft(2, '0')}日，${weekNames[date.weekday - 1]}';
              } else {
                dateText = sleepInfoData.dailyValue;
              }
            } catch (e) {
              dateText = sleepInfoData.dailyValue;
            }
          } else {
            // 如果没有 API 数据，使用当前日期
            final now = DateTime.now();
            const List<String> weekNames = [
              '周一',
              '周二',
              '周三',
              '周四',
              '周五',
              '周六',
              '周日'
            ];
            dateText =
                '${now.year}年${now.month.toString().padLeft(2, '0')}月${now.day.toString().padLeft(2, '0')}日，${weekNames[now.weekday - 1]}';
          }
          break;
        case TimeRange.week:
          // 从 API 数据中获取周睡眠详情
          final sleepInfoData = controller.state.sleepInfoData.value;
          if (sleepInfoData != null && sleepInfoData.average != null) {
            // 使用周/月专用字段
            totalDurationText = sleepInfoData.average!.replaceAll('分', '分钟');
            mainSleepText = sleepInfoData.longAverage ?? '0小时 0分';
            napSleepText = sleepInfoData.shortAverage ?? '0小时 0分';
            dateText = '${sleepInfoData.dateStart} - ${sleepInfoData.dateEnd}';
          } else {
            // 降级使用旧字段
            totalDurationText = controller.state.weeklySleepTime.value.replaceAll('分', '分钟');
            mainSleepText = controller.state.weeklySleepTime.value;
            napSleepText = '0小时 0分';
            dateText = '本周平均';
          }
          break;
        case TimeRange.month:
          // 从 API 数据中获取月睡眠详情
          final sleepInfoData = controller.state.sleepInfoData.value;
          if (sleepInfoData != null && sleepInfoData.average != null) {
            // 使用周/月专用字段
            totalDurationText = sleepInfoData.average!.replaceAll('分', '分钟');
            mainSleepText = sleepInfoData.longAverage ?? '0小时 0分';
            napSleepText = sleepInfoData.shortAverage ?? '0小时 0分';
            dateText = '${sleepInfoData.dateStart} - ${sleepInfoData.dateEnd}';
          } else {
            // 降级使用旧字段
            totalDurationText = controller.state.monthlySleepTime.value.replaceAll('分', '分钟');
            mainSleepText = controller.state.monthlySleepTime.value;
            napSleepText = '0小时 0分';
            final now = DateTime.now();
            dateText = '${now.year}年${now.month}月平均';
          }
          break;
      }
      return Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              _buildRichDuration(totalDurationText,
                  numberSize: 38.sp, unitSize: 14.sp),
            ],
          ),
          SizedBox(height: 6.h),
          Text(
            dateText,
            style: TextStyle(
              fontSize: 12.sp,
              color: Colors.white,
            ),
          ),
          SizedBox(height: 14.h),
          Container(
            padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.h),
            decoration: BoxDecoration(
              color: Colors.white.withOpacity(0.08),
              borderRadius: BorderRadius.circular(12.r),
              border:
                  Border.all(color: Colors.white.withOpacity(0.12), width: 1),
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Expanded(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(
                        '睡眠：',
                        style: TextStyle(
                            fontSize: 13.sp,
                            color: Colors.white.withOpacity(0.9)),
                      ),
                      _buildRichDuration(mainSleepText,
                          numberSize: 15.sp, unitSize: 11.sp),
                    ],
                  ),
                ),
                Container(
                  width: 1.w,
                  height: 18.h,
                  margin: EdgeInsets.symmetric(horizontal: 14.w),
                  color: Colors.white.withOpacity(0.2),
                ),
                Expanded(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(
                        '小睡：',
                        style: TextStyle(
                            fontSize: 13.sp,
                            color: Colors.white.withOpacity(0.9)),
                      ),
                      _buildRichDuration(napSleepText,
                          numberSize: 15.sp, unitSize: 11.sp),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ],
      );
    });
  }

  /// 构建“数字大、文字小”的时长富文本
  Widget _buildRichDuration(String text,
      {double numberSize = 56, double unitSize = 18}) {
    final RegExp digitExp = RegExp(r'[0-9]');
    final List<TextSpan> spans = <TextSpan>[];
    final TextStyle numberStyle = TextStyle(
      fontSize: numberSize,
      fontWeight: FontWeight.w700,
      color: Colors.white,
      height: 1.0,
    );
    final TextStyle unitStyle = TextStyle(
      fontSize: unitSize,
      fontWeight: FontWeight.w500,
      color: Color(0xffF9F8F7),
      height: 1.6,
    );
    for (int i = 0; i < text.length; i++) {
      final String ch = text[i];
      final bool isDigit = digitExp.hasMatch(ch);
      spans.add(TextSpan(text: ch, style: isDigit ? numberStyle : unitStyle));
    }
    return RichText(text: TextSpan(children: spans));
  }



  /// 构建睡眠阶段图表
  Widget _buildSleepChart() {
    return Obx(() {
      // 周/月视图：显示堆叠柱状图
      if (currentTimeRange == TimeRange.week || currentTimeRange == TimeRange.month) {
        final sleepInfoData = controller.state.sleepInfoData.value;
        if (sleepInfoData != null && sleepInfoData.ringWeekOrMonthSleepVOS != null) {
          return _buildWeekMonthBarChart(sleepInfoData.ringWeekOrMonthSleepVOS!);
        } else {
          return Container(
            height: 280.h,
            padding: EdgeInsets.all(16.w),
            child: Center(
              child: Text(
                '--',
                style: TextStyle(
                  fontSize: 32.sp,
                  color: Colors.white.withOpacity(0.3),
                ),
              ),
            ),
          );
        }
      }
      
      // 日视图：显示睡眠阶段时间轴
      final sleepInfoData = controller.state.sleepInfoData.value;
      final hasData = sleepInfoData != null && sleepInfoData.maps != null;

      if (!hasData) {
        return Container(
          height: 280.h,
          padding: EdgeInsets.all(16.w),
          child: Center(
            child: Text(
              '--',
              style: TextStyle(
                fontSize: 32.sp,
                color: Colors.white.withOpacity(0.3),
              ),
            ),
          ),
        );
      }

      // 获取开始和结束时间
      final startTime = sleepInfoData.startDate.split(' ').length > 1
          ? sleepInfoData.startDate.split(' ')[1].substring(0, 5)
          : '--';
      final endTime = sleepInfoData.endDate.split(' ').length > 1
          ? sleepInfoData.endDate.split(' ')[1].substring(0, 5)
          : '--';

      return Container(
        height: 280.h,
        padding: EdgeInsets.all(5.w),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: SizedBox(
                width: double.infinity,
                child: CustomPaint(
                  painter: SleepStageTimelinePainter(
                    sleepMaps: sleepInfoData.maps ?? {},
                    startDate: sleepInfoData.startDate,
                    endDate: sleepInfoData.endDate,
                  ),
                ),
              ),
            ),
            SizedBox(
              height: 20.h,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(startTime,
                      style: TextStyle(
                          fontSize: 12.sp,
                          color: Colors.white.withOpacity(0.7))),
                  Text(endTime,
                      style: TextStyle(
                          fontSize: 12.sp,
                          color: Colors.white.withOpacity(0.7))),
                ],
              ),
            ),
            Container(
                height: 15.h, child: CustomPaint(painter: TimeTicksPainter())),            
          ],
        ),
      );
    });
  }

  /// 构建周/月柱状图（使用 ringWeekOrMonthSleepVOS 数据）
  Widget _buildWeekMonthBarChart(List<DailySleepDetail> sleepDetails) {
    // 四段堆叠：深睡(底)、浅睡(第二层)、快速眼动(第三层)、清醒(顶)
    const Color deepColor = Color(0xFF4B241A); // 深睡眠 - 深棕色
    const Color lightColor = Color(0xFFE76234); // 浅睡眠 - 红橙色
    const Color remColor = Color(0xFFFFC066); // 快速眼动 - 橙色
    const Color awakeColor = Color(0xFFE0E0E0); // 清醒 - 浅灰色
    const double between = 0.0; // 阶段之间没有边距

    BarChartGroupData generate(int x, double deep, double light, double rem, double awake) {
      return BarChartGroupData(
        x: x,
        groupVertically: true,
        barRods: [
          BarChartRodData(
              fromY: 0,
              toY: deep,
              color: deepColor,
              width: 16.w,
              borderRadius: BorderRadius.circular(4.r)),
          BarChartRodData(
              fromY: deep + between,
              toY: deep + between + light,
              color: lightColor,
              width: 16.w,
              borderRadius: BorderRadius.circular(4.r)),
          BarChartRodData(
              fromY: deep + between + light + between,
              toY: deep + between + light + between + rem,
              color: remColor,
              width: 16.w,
              borderRadius: BorderRadius.circular(4.r)),
          BarChartRodData(
              fromY: deep + between + light + between + rem + between,
              toY: deep + between + light + between + rem + between + awake,
              color: awakeColor,
              width: 16.w,
              borderRadius: BorderRadius.circular(4.r)),
        ],
      );
    }

    // 构建柱状图数据
    final List<BarChartGroupData> groups = [];
    final List<String> dates = [];
    final List<double> totalHeights = [];

    for (int i = 0; i < sleepDetails.length; i++) {
      final detail = sleepDetails[i];
      dates.add(detail.dailyValue);

      if (detail.weekOrMonthSleeps.length >= 4) {
        // weekOrMonthSleeps 顺序: [0]=awake, [1]=rem, [2]=light, [3]=deep
        final awakeHours = detail.weekOrMonthSleeps[0].value / 60.0;
        final remHours = detail.weekOrMonthSleeps[1].value / 60.0;
        final lightHours = detail.weekOrMonthSleeps[2].value / 60.0;
        final deepHours = detail.weekOrMonthSleeps[3].value / 60.0;

        final hasData = awakeHours > 0 || remHours > 0 || lightHours > 0 || deepHours > 0;

        if (hasData) {
          final totalHeight = deepHours + lightHours + remHours + awakeHours + (between * 3);
          totalHeights.add(totalHeight);
          groups.add(generate(i, deepHours, lightHours, remHours, awakeHours));
        } else {
          totalHeights.add(0);
          groups.add(BarChartGroupData(x: i, barRods: []));
        }
      } else {
        totalHeights.add(0);
        groups.add(BarChartGroupData(x: i, barRods: []));
      }
    }

    Widget bottomTitle(double value, TitleMeta meta) {
      final int i = value.toInt();
      if (i < 0 || i >= dates.length) return const SizedBox.shrink();
      
      // 根据时间范围决定显示哪些标签
      bool shouldDisplay = false;
      if (currentTimeRange == TimeRange.week) {
        shouldDisplay = true; // 周视图显示所有日期
      } else if (currentTimeRange == TimeRange.month) {
        // 月视图只显示特定日期
        try {
          final dayNum = int.parse(dates[i]);
          shouldDisplay = (dayNum == 1 || dayNum % 5 == 0);
        } catch (e) {
          shouldDisplay = (i == 0 || i == dates.length - 1);
        }
      }
      
      if (!shouldDisplay) return const SizedBox.shrink();
      
      return SideTitleWidget(
          axisSide: meta.axisSide,
          space: 6,
          child: Text(dates[i],
              style: TextStyle(
                  fontSize: 12.sp, color: const Color(0xff6C6B6A))));
    }

    return Column(children: [
      SizedBox(
        height: 220.h,
        child: Stack(
          children: [
            // 连接线层
            CustomPaint(
              size: Size.infinite,
              painter: SleepTrendLinePainter(
                totalHeights: totalHeights,
                dataCount: groups.length,
                maxY: 12,
              ),
            ),
            // 柱状图层
            BarChart(
              BarChartData(
                alignment: BarChartAlignment.spaceBetween,
                maxY: 12,
                titlesData: FlTitlesData(
                  leftTitles: AxisTitles(
                    sideTitles: SideTitles(
                      showTitles: true,
                      interval: 1,
                      reservedSize: 60,
                      getTitlesWidget: (v, m) {
                        final labels = ['', '深睡眠', '', '', '浅睡眠', '', '', '快速眼动', '', '', '清醒', ''];
                        final index = v.toInt();
                        if (index >= 0 && index < labels.length && labels[index].isNotEmpty) {
                          return Text(labels[index],
                              style: TextStyle(
                                  fontSize: 11.sp,
                                  color: const Color(0xff5A5A5A)));
                        }
                        return const SizedBox.shrink();
                      },
                    ),
                  ),
                  rightTitles:
                      const AxisTitles(sideTitles: SideTitles(showTitles: false)),
                  topTitles:
                      const AxisTitles(sideTitles: SideTitles(showTitles: false)),
                  bottomTitles: AxisTitles(
                      sideTitles: SideTitles(
                          showTitles: true,
                          getTitlesWidget: bottomTitle,
                          reservedSize: 22)),
                ),
                barTouchData: BarTouchData(enabled: false),
                borderData: FlBorderData(show: false),
                gridData: const FlGridData(show: false),
                barGroups: groups,
              ),
            ),
          ],
        ),
      ),
    ]);
  }

  /// 构建睡眠详情
  Widget _buildSleepDetails({bool inner = false}) {
    return Obx(() {
      // 从 controller.state 获取数据
      final score = controller.state.dailySleepScore.value;
      final hasData = score > 0;

      return Container(
        padding: EdgeInsets.all(12.w),
        decoration: BoxDecoration(
          color: inner ? Colors.transparent : const Color.fromRGBO(3, 0, 3, 1),
          borderRadius: BorderRadius.circular(16.r),
        ),
        child: !hasData
            ? Center(
                child: Padding(
                  padding: EdgeInsets.symmetric(vertical: 40.h),
                  child: Text(
                    '--',
                    style: TextStyle(
                      fontSize: 32.sp,
                      color: Colors.white.withOpacity(0.3),
                    ),
                  ),
                ),
              )
            : Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  SizedBox(height: 18.h),
                  LayoutBuilder(
                    builder:
                        (BuildContext context, BoxConstraints constraints) {
                      final double barWidth = constraints.maxWidth;
                      final double indicatorWidth = 12.w;
                      final double leftOffset =
                          (barWidth * (score / 100)).clamp(0.0, barWidth);
                      return Stack(
                        clipBehavior: Clip.none,
                        children: [
                          SizedBox(height: 10.h),
                          // 分数与单位，位置与指示器对齐
                          Positioned(
                            left: (leftOffset - indicatorWidth / 2)
                                    .clamp(0.0, barWidth - indicatorWidth) -
                                40.w,
                            top: -40.h,
                            child: SizedBox(
                              height: 40.h,
                              child: Row(
                                crossAxisAlignment: CrossAxisAlignment.end,
                                children: [
                                  Text(
                                    '$score',
                                    style: TextStyle(
                                      fontSize: 28.sp,
                                      fontWeight: FontWeight.w500,
                                      color: Colors.white,
                                      height: 1.0,
                                    ),
                                  ),
                                  SizedBox(width: 6.w),
                                  Text('分',
                                      style: TextStyle(
                                          fontSize: 16.sp,
                                          color:
                                              Colors.white.withOpacity(0.9))),
                                ],
                              ),
                            ),
                          ),
                          Container(
                            height: 12.h,
                            decoration: BoxDecoration(
                              color: Colors.white.withOpacity(0.08),
                              borderRadius: BorderRadius.circular(6.r),
                            ),
                            child: FractionallySizedBox(
                              alignment: Alignment.centerLeft,
                              widthFactor: score / 100,
                              child: Container(
                                decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(6.r),
                                  gradient: const LinearGradient(
                                    begin: Alignment.centerLeft,
                                    end: Alignment.centerRight,
                                    colors: [
                                      Color(0xFFF06C2B),
                                      Color(0xFFE24A12)
                                    ],
                                  ),
                                ),
                              ),
                            ),
                          ),
                          Positioned(
                            left: (leftOffset - indicatorWidth / 2)
                                .clamp(0.0, barWidth - indicatorWidth),
                            top: 12.h,
                            child: Assets.sleep.progressTriangle.image(
                              width: 14.w,
                              height: 7.h,
                              color: null,
                            ),
                          ),
                        ],
                      );
                    },
                  ),
                  SizedBox(height: 25.h),
                  Obx(() {
                    // 从 API 数据获取 summary
                    final qualityData = controller.state.sleepQualityData.value;
                    final summary = qualityData?.summary ?? '--';
                    
                    return Text(
                      summary,
                      style: TextStyle(
                          fontSize: 12.sp,
                          color: const Color(0xff656565),
                          height: 1.35),
                    );
                  }),
                  SizedBox(height: 12.h),
                  Obx(() {
                    // 从 state 获取数据
                    final qualityData = controller.state.sleepQualityData.value;
                    final sleepDuration = qualityData?.sleepDuration ?? '--';
                    final sleepLatency =
                        controller.state.dailySleepLatency.value;
                    final sleepEfficiency = qualityData?.sleepEfficiency;
                    final timing = qualityData?.timing ?? '--';

                    return GridView(
                      shrinkWrap: true,
                      physics: const NeverScrollableScrollPhysics(),
                      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 2,
                        mainAxisSpacing: 10.h,
                        crossAxisSpacing: 10.w,
                        mainAxisExtent: 71.h,
                      ),
                      children: [
                        _buildStatCard(
                            title: '卧床时间',
                            value: sleepDuration,
                            iconWidget: Assets.sleep.bedTime.image()),
                        _buildStatCard(
                            title: '睡眠潜伏期',
                            value:
                                sleepLatency > 0 ? '${sleepLatency}分钟' : '--',
                            iconWidget: Assets.sleep.sleep.image()),
                        _buildStatCard(
                            title: '睡眠效率',
                            value: sleepEfficiency != null
                                ? '${sleepEfficiency}%'
                                : '--',
                            iconWidget: Assets.sleep.effient.image()),
                        _buildStatCard(
                            title: '时机',
                            value: timing,
                            iconWidget: Assets.sleep.time.image()),
                      ],
                    );
                  }),
                ],
              ),
      );
    });
  }

  Widget _buildStatCard({
    required String title,
    required String value,
    IconData? iconData,
    Widget? iconWidget,
  }) {
    return Container(
      height: 301.h,
      decoration: BoxDecoration(
        color: const Color.fromRGBO(40, 37, 40, 1),
        borderRadius: BorderRadius.circular(12.r),
        border:
            Border.all(color: const Color.fromRGBO(33, 33, 33, 1), width: 1),
      ),
      padding: EdgeInsets.symmetric(horizontal: 13.w, vertical: 14.h),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // 第一行：数值（数字更大，单位略小）
          _buildValueRichText(value),
          SizedBox(height: 2.h),
          // 第二行：图标 + 描述
          Row(
            children: [
              if (iconWidget != null)
                SizedBox(
                  width: 14.sp,
                  height: 14.sp,
                  child: iconWidget,
                )
              else if (iconData != null)
                Icon(iconData,
                    color: Colors.white.withOpacity(0.9), size: 14.sp),
              SizedBox(width: 6.w),
              Expanded(
                child: Text(
                  title,
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                  style: TextStyle(
                      fontSize: 12.sp, color: Colors.white.withOpacity(0.9)),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

  /// 将类似“6小时45分钟 / 99% / 2分钟 / 良”拆成数字和单位的富文本
  Widget _buildValueRichText(String value) {
    final RegExp digitExp = RegExp(r'[0-9]');
    final List<TextSpan> spans = <TextSpan>[];
    final TextStyle numStyle = TextStyle(
        fontSize: 18.sp,
        fontWeight: FontWeight.w700,
        color: Colors.white,
        height: 1.0);
    final TextStyle unitStyle = TextStyle(
        fontSize: 13.sp,
        fontWeight: FontWeight.w500,
        color: Colors.white,
        height: 1.2);
    for (int i = 0; i < value.length; i++) {
      final String ch = value[i];
      spans.add(TextSpan(
          text: ch, style: digitExp.hasMatch(ch) ? numStyle : unitStyle));
    }
    return RichText(text: TextSpan(children: spans));
  }

  /// 睡眠比例区块（使用 fl_chart 的环图）
  Widget _buildSleepRatioSection() {
    return Obx(() {
      final hasData = controller.state.dailySleepTime.value != '--';

      if (!hasData) {
        return Center(
          child: Padding(
            padding: EdgeInsets.symmetric(vertical: 40.h),
            child: Text(
              '--',
              style: TextStyle(
                fontSize: 32.sp,
                color: Colors.white.withOpacity(0.3),
              ),
            ),
          ),
        );
      }

      // 从 state 获取睡眠比例数据
      final proportionData = controller.state.sleepProportionData.value;

      // 根据当前时间范围决定显示格式
      final bool isWeekOrMonth = currentTimeRange == TimeRange.week || currentTimeRange == TimeRange.month;

      final List<_StageData> stages = [
        _StageData(
            label: isWeekOrMonth ? '平均深睡眠' : '深睡眠',
            ref: '参考值15%–25%',
            time: proportionData?.deep?.sleepDuration ?? '--',
            percent: proportionData?.deep?.proportion != null
                ? '${proportionData?.deep?.proportion}%'
                : '--',
            rateValue: proportionData?.deep?.rateValue,
            color: const Color(0xFFE76234)),
        _StageData(
            label: isWeekOrMonth ? '平均浅睡眠' : '浅睡眠',
            ref: '参考值50%–60%',
            time: proportionData?.light?.sleepDuration ?? '--',
            percent: proportionData?.light?.proportion != null
                ? '${proportionData?.light?.proportion}%'
                : '--',
            rateValue: proportionData?.light?.rateValue,
            color: const Color(0xFFFFBD6E)),
        _StageData(
            label: isWeekOrMonth ? '平均快速眼动' : '快速眼动',
            ref: '参考值20%–25%',
            time: proportionData?.rem?.sleepDuration ?? '--',
            percent: proportionData?.rem?.proportion != null
                ? '${proportionData?.rem?.proportion}%'
                : '--',
            rateValue: proportionData?.rem?.rateValue,
            color: const Color(0xFFD9DBDD)),
        _StageData(
            label: isWeekOrMonth ? '平均清醒时长' : '清醒时长',
            ref: '参考值3%–5%',
            time: proportionData?.awake?.sleepDuration ?? '--',
            percent: proportionData?.awake?.proportion != null
                ? '${proportionData?.awake?.proportion}%'
                : '--',
            rateValue: proportionData?.awake?.rateValue,
            color: const Color(0xFF3B2018)),
      ];
      
      // 周/月视图：纵向列表布局（不显示环形图）
      if (isWeekOrMonth) {
        return Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: List.generate(stages.length * 2 - 1, (int i) {
            if (i.isOdd) {
              return SizedBox(height: 12.h);
            }
            final int idx = i ~/ 2;
            final _StageData e = stages[idx];
            return _buildStageItem(
              color: e.color,
              label: e.label,
              refText: e.ref,
              timeText: e.time,
              percentText: e.percent,
              rateValue: e.rateValue,
              isWeekOrMonth: isWeekOrMonth,
            );
          }),
        );
      }
      
      // 日视图：环形图 + 列表布局
      return SizedBox(
        child: Row(
          children: [
            // 左侧环形图（fl_chart）
            Padding(
              padding: EdgeInsets.only(left: 6.w, right: 12.w),
              child: SizedBox(
                width: 106.w, // 控制整体宽度
                height: 106.w, // 控制整体高度（通常与宽度相等以保持圆形）
                child: PieChart(
                  PieChartData(
                    sectionsSpace: 0, // 扇区间距
                    centerSpaceRadius: 30.w, // 中心空白半径（内环半径）
                    borderData: FlBorderData(show: false),
                    sections: _buildPieSections(stages),
                  ),
                ),
              ),
            ),
            SizedBox(width: 12.w),
            // 右侧列表
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: List.generate(stages.length * 2 - 1, (int i) {
                  if (i.isOdd) {
                    return SizedBox(height: 8.h);
                  }
                  final int idx = i ~/ 2;
                  final _StageData e = stages[idx];
                  return _buildStageItem(
                    color: e.color,
                    label: e.label,
                    refText: e.ref,
                    timeText: e.time,
                    percentText: e.percent,
                    rateValue: e.rateValue,
                    isWeekOrMonth: isWeekOrMonth,
                  );
                }),
              ),
            ),
          ],
        ),
      );
    });
  }

  List<PieChartSectionData> _buildPieSections(List<_StageData> stages) {
    final List<_StageData> top4 =
        stages.length >= 4 ? stages.sublist(0, 4) : stages;
    return top4
        .map((s) => PieChartSectionData(
              color: s.color,
              value: s.percentValue,
              title: '',
              radius: 20.w,
              showTitle: false,
            ))
        .toList();
  }

  Widget _buildStageItem({
    required Color color,
    required String label,
    required String refText,
    required String timeText,
    required String percentText,
    String? rateValue,
    bool isWeekOrMonth = false,
  }) {
    // 周/月视图：左边（圆点+标签+参考值）、中间（评价标签）、右边（时长和百分比上下排列）
    if (isWeekOrMonth) {
      return Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          // 左边：圆点
          Container(
            width: 32.w,
            height: 32.w,
            decoration: BoxDecoration(
              color: color,
              shape: BoxShape.circle,
            ),
          ),
          SizedBox(width: 12.w),
          // 左边：标签 + 参考值
          Expanded(
            flex: 2,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(label,
                    style: TextStyle(
                        fontSize: 14.sp,
                        fontWeight: FontWeight.w500,
                        color: Colors.white)),
                SizedBox(height: 2.h),
                Text(refText,
                    style: TextStyle(
                        fontSize: 11.sp, color: const Color(0xff908E8D))),
              ],
            ),
          ),
          SizedBox(width: 12.w),
          // 中间：评价标签
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              _buildRateTag('偏少', rateValue == '偏少'),
              SizedBox(width: 6.w),
              _buildRateTag('适中', rateValue == '适中'),
              SizedBox(width: 6.w),
              _buildRateTag('偏多', rateValue == '偏多'),
            ],
          ),
          SizedBox(width: 16.w),
          // 右边：时长和百分比上下排列
          Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              _buildValueRichText(timeText),
              SizedBox(height: 2.h),
              Text(percentText,
                  style: TextStyle(
                      fontSize: 13.sp, color: const Color(0xff908E8D))),
            ],
          ),
        ],
      );
    }
    
    // 日视图：保持原有布局
    return Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Container(
            width: 3.w,
            height: 28.h,
            decoration: BoxDecoration(
                color: color, borderRadius: BorderRadius.circular(2.r))),
        SizedBox(width: 8.w),
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(label,
                  style: TextStyle(
                      fontSize: 13.sp,
                      fontWeight: FontWeight.w500,
                      color: const Color(0xff908E8D))),
              SizedBox(height: 2.h),
              Text(refText,
                  style: TextStyle(
                      fontSize: 10.sp, color: const Color(0xff5A5A5A))),
            ],
          ),
        ),
        Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            _buildValueRichText(timeText),
            SizedBox(height: 2.h),
            Text(percentText,
                style:
                    TextStyle(fontSize: 12.sp, color: const Color(0xff908E8D))),
          ],
        ),
      ],
    );
  }

  /// 构建评价标签
  Widget _buildRateTag(String text, bool isActive) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.h),
      decoration: BoxDecoration(
        color: isActive
            ? _getRateValueActiveColor(text)
            : const Color(0xFF3A3A3A),
        borderRadius: BorderRadius.circular(12.r),
      ),
      child: Text(
        text,
        style: TextStyle(
          fontSize: 11.sp,
          color: isActive ? Colors.white : const Color(0xFF6C6B6A),
          fontWeight: isActive ? FontWeight.w600 : FontWeight.w400,
        ),
      ),
    );
  }

  /// 根据评价值获取激活状态的颜色
  Color _getRateValueActiveColor(String rateValue) {
    switch (rateValue) {
      case '适中':
        return const Color(0xFF00C08B); // 绿色
      case '偏少':
        return const Color(0xFFFF8C42); // 橙色
      case '偏多':
        return const Color(0xFFE76234); // 红橙色
      default:
        return const Color(0xFF6C6B6A); // 灰色
    }
  }

  /// 小睡区块
  Widget _buildNapSection() {
    return Obx(() {
      // 从 state 获取小睡数据
      final shortSleepData = controller.state.shortSleepData.value;
      
      final hasNapData = shortSleepData != null && 
                         shortSleepData.shortSleepDates.isNotEmpty;

      // 根据时间范围显示不同的视图
      if (currentTimeRange == TimeRange.day) {
        // 日视图：显示单日小睡时间轴
        
        // 获取平均小睡时长
        final totalNap = hasNapData ? shortSleepData!.sleepDuration : '-小时 -分钟';
        
        // 根据当前时间范围获取对应的小睡时间段
        String napStartTime = '00:00';
        String napEndTime = '00:00';
        
        // 对于日视图，获取当天的小睡时间
        if (hasNapData && shortSleepData!.shortSleepDates.isNotEmpty) {
          final todayData = shortSleepData.shortSleepDates.first;
          
          if (todayData.shortSleepTimes != null && todayData.shortSleepTimes!.isNotEmpty) {
            final firstNap = todayData.shortSleepTimes!.first;
            napStartTime = firstNap.startDate;
            napEndTime = firstNap.endDate;
          }
        }
        
        final timeRange = '$napStartTime–$napEndTime';

        // 计算小睡在时间轴上的位置
        // 将时间转换为分钟数（从00:00开始）
        int startMinutes = 0;
        int endMinutes = 0;
        
        if (hasNapData) {
          try {
            final startParts = napStartTime.split(':');
            final endParts = napEndTime.split(':');
            if (startParts.length >= 2 && endParts.length >= 2) {
              startMinutes = int.parse(startParts[0]) * 60 + int.parse(startParts[1]);
              endMinutes = int.parse(endParts[0]) * 60 + int.parse(endParts[1]);
            }
          } catch (e) {
            // 如果解析失败，使用默认值 0
            print('解析小睡时间失败: $e');
          }
        }
        
        // 计算位置百分比（24小时 = 1440分钟）
        final double startPercent = startMinutes / 1440.0;
        final double endPercent = endMinutes / 1440.0;
        final double napDuration = endPercent - startPercent;

        // 科学补觉区间：13:00-14:00
        const double recommendStartPercent = (13 * 60) / 1440.0; // 13:00
        const double recommendEndPercent = (14 * 60) / 1240.0;   // 14:00

        return Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            SizedBox(height: 8.h),
            // 顶部总时长 + 时间范围
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.end,
              children: [
                _buildValueRichText(totalNap),
                SizedBox(width: 10.w),
                Text(
                  timeRange,
                  style:
                      TextStyle(fontSize: 14.sp, color: const Color(0xff6C6B6A)),
                ),
              ],
            ),
            SizedBox(height: 8.h),
            // 文案
            Text(
              '科学补觉区间',
              style: TextStyle(fontSize: 14.sp, color: const Color(0xFF2F7BFF)),
            ),
            SizedBox(height: 10.h),
            // 进度条
            LayoutBuilder(
              builder: (context, constraints) {
                final barWidth = constraints.maxWidth - 20.w;
                
                return Container(
                  height: 28.h,
                  decoration: BoxDecoration(
                    color: const Color(0xFF2F2B2C),
                    borderRadius: BorderRadius.circular(14.r),
                  ),
                  padding: EdgeInsets.symmetric(horizontal: 10.w),
                  child: Stack(
                    children: [
                      // 虚线框（建议区间 13:00-15:00）
                      Positioned(
                        left: barWidth * recommendStartPercent,
                        top: 4.h,
                        bottom: 4.h,
                        child: Container(
                          width: barWidth * (recommendEndPercent - recommendStartPercent),
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(10.r),
                            border: Border.all(
                                color: const Color(0xFF2F7BFF),
                                width: 1,
                                style: BorderStyle.solid),
                          ),
                        ),
                      ),
                      // 实际小睡块
                      if (napDuration > 0)
                        Positioned(
                          left: barWidth * startPercent,
                          top: 4.h,
                          bottom: 4.h,
                          child: Container(
                            width: (barWidth * napDuration).clamp(20.w, barWidth),
                            decoration: BoxDecoration(
                              color: const Color(0xFFE76234),
                              borderRadius: BorderRadius.circular(10.r),
                            ),
                          ),
                        ),
                    ],
                  ),
                );
              },
            ),
            SizedBox(height: 8.h),
            // 时间刻度
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text('00:00',
                    style: TextStyle(
                        fontSize: 14.sp, color: const Color(0xff6C6B6A))),
                Text('13:00–15:00',
                    style: TextStyle(
                        fontSize: 16.sp, color: const Color(0xFF2F7BFF))),
                Text('24:00',
                    style: TextStyle(
                        fontSize: 14.sp, color: const Color(0xff6C6B6A))),
              ],
            ),
          ],
        );
      } else {
        // 周/月视图：显示多日小睡柱状图
        if (!hasNapData) {
          return Center(
            child: Padding(
              padding: EdgeInsets.symmetric(vertical: 40.h),
              child: Text(
                '--',
                style: TextStyle(
                  fontSize: 32.sp,
                  color: Colors.white.withOpacity(0.3),
                ),
              ),
            ),
          );
        }
        return _buildNapChart(shortSleepData);
      }
    });
  }

  /// 构建小睡柱状图（周/月视图）
  Widget _buildNapChart(ShortSleepData shortSleepData) {
    return Column(
      children: [
        SizedBox(height: 8.h),
        // 平均值
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            _buildValueRichText(shortSleepData.sleepDuration),
            SizedBox(width: 10.w),
            Text(
              '平均值',
              style: TextStyle(fontSize: 14.sp, color: const Color(0xff6C6B6A)),
            ),
          ],
        ),
        SizedBox(height: 16.h),
        // 图表区域（带左侧时间刻度）
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 左侧时间刻度
            SizedBox(
              width: 60.w,
              height: 180.h,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('00:00', style: TextStyle(fontSize: 11.sp, color: const Color(0xff6C6B6A))),
                  Text('06:00', style: TextStyle(fontSize: 11.sp, color: const Color(0xff6C6B6A))),
                  Text('12:00', style: TextStyle(fontSize: 11.sp, color: const Color(0xff6C6B6A))),
                  Text('18:00', style: TextStyle(fontSize: 11.sp, color: const Color(0xff6C6B6A))),
                  Text('24:00', style: TextStyle(fontSize: 11.sp, color: const Color(0xff6C6B6A))),
                ],
              ),
            ),
            SizedBox(width: 8.w),
            // 柱状图
            Expanded(
              child: Column(
                children: [
                  SizedBox(
                    height: 180.h,
                    child: CustomPaint(
                      painter: NapChartPainter(
                        napData: shortSleepData,
                        timeRange: currentTimeRange,
                      ),
                      child: Container(),
                    ),
                  ),
                  SizedBox(height: 8.h),
                  // 底部日期标签 - 根据时间范围决定显示哪些标签
                  SizedBox(
                    height: 24.h, // 增加高度确保文字完全显示
                    child: LayoutBuilder(
                      builder: (context, constraints) {
                        final dataCount = shortSleepData.shortSleepDates.length;
                        final barSpacing = constraints.maxWidth / (dataCount + 1);
                        
                        return Stack(
                          children: List.generate(dataCount, (index) {
                            final date = shortSleepData.shortSleepDates[index];
                            final x = barSpacing * (index + 1);
                            
                            // 判断是否应该显示这个日期标签
                            bool shouldDisplay = false;
                            
                            if (currentTimeRange == TimeRange.week) {
                              // 周视图：显示所有日期
                              shouldDisplay = true;
                            } else if (currentTimeRange == TimeRange.month) {
                              // 月视图：只显示特定日期
                              try {
                                final dayNum = int.parse(date.dailyValue);
                                // 显示1, 5, 10, 15, 20, 25, 30
                                shouldDisplay = (dayNum == 1 || dayNum % 5 == 0);
                              } catch (e) {
                                // 如果解析失败，显示第一个和最后一个
                                shouldDisplay = (index == 0 || index == dataCount - 1);
                              }
                            }
                            
                            if (!shouldDisplay) {
                              return const SizedBox.shrink();
                            }
                            
                            // 计算左边距，确保不会超出边界
                            final double leftPosition = (x - 20.w).clamp(0.0, constraints.maxWidth - 40.w);
                            
                            return Positioned(
                              left: leftPosition,
                              top: 0, // 明确指定顶部位置
                              child: Container(
                                width: 40.w,
                                height: 24.h,
                                alignment: Alignment.center,
                                child: Text(
                                  date.dailyValue,
                                  textAlign: TextAlign.center,
                                  style: TextStyle(
                                    fontSize: 12.sp, // 稍微增大字体
                                    color: Colors.white.withOpacity(0.7), // 使用更明显的颜色
                                    fontWeight: FontWeight.w500,
                                  ),
                                ),
                              ),
                            );
                          }),
                        );
                      },
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
        SizedBox(height: 8.h),
        // 科学补觉区间说明
        Text(
          '科学补觉区间',
          style: TextStyle(fontSize: 12.sp, color: const Color(0xFF2F7BFF)),
        ),
      ],
    );
  }

  /// 平均睡眠心率折线图
  Widget _buildAvgSleepHeartRateSection() {
    return Obx(() {
      final heartRateData = controller.state.sleepHeartRateData.value;
      final timeRange = currentTimeRange;

      // 周/月视图：显示柱状图
      if (timeRange == TimeRange.week || timeRange == TimeRange.month) {
        return _buildMetricBarChart(
          heartRateData,
          '平均睡眠心率',
          'bpm',
          MetricType.heartRate,
        );
      }

      // 日视图：显示折线图
      final hasData =
          heartRateData != null && heartRateData.dataList.isNotEmpty;

      if (!hasData) {
        return Center(
          child: Padding(
            padding: EdgeInsets.symmetric(vertical: 40.h),
            child: Text(
              '--',
              style: TextStyle(
                fontSize: 32.sp,
                color: Colors.white.withOpacity(0.3),
              ),
            ),
          ),
        );
      }

      // 构建数据点
      final List<FlSpot> spots = [];
      for (int i = 0; i < heartRateData.dataList.length; i++) {
        spots.add(
            FlSpot(i.toDouble(), heartRateData.dataList[i].value.toDouble()));
      }

      // 获取开始和结束时间
      final startTime = heartRateData.dataList.first.key;
      final endTime = heartRateData.dataList.last.key;

      return Column(
        children: [
          // 平均值和范围
          Padding(
            padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h),
            child: Row(
              children: [
                _buildValueRichText('${heartRateData.average} bpm平均值'),
                Spacer(),
                Text(
                  '正常范围: 50-100次',
                  style: TextStyle(
                    fontSize: 12.sp,
                    color: const Color(0xff6C6B6A),
                  ),
                ),
              ],
            ),
          ),
          Stack(
            children: [
              SizedBox(
                height: 220.h,
                child: LineChart(
                  LineChartData(
                    minY: 0,
                    maxY: 120,
                    borderData: FlBorderData(show: false),
                    lineTouchData: const LineTouchData(enabled: false),
                    titlesData: FlTitlesData(
                      leftTitles: AxisTitles(
                        sideTitles: SideTitles(
                          showTitles: true,
                          reservedSize: 32,
                          interval: 50,
                          getTitlesWidget: (value, meta) => Text(
                            value.toInt().toString(),
                            style: TextStyle(
                                fontSize: 11.sp,
                                color: const Color(0xff6C6B6A)),
                          ),
                        ),
                      ),
                      rightTitles: const AxisTitles(
                          sideTitles: SideTitles(showTitles: false)),
                      topTitles: const AxisTitles(
                          sideTitles: SideTitles(showTitles: false)),
                      bottomTitles: AxisTitles(
                        sideTitles: SideTitles(
                          showTitles: true,
                          interval: spots.length > 1
                              ? (spots.length - 1).toDouble()
                              : 1,
                          getTitlesWidget: (value, meta) {
                            if (value == 0) {
                              return Text(startTime,
                                  style: TextStyle(
                                      fontSize: 11.sp,
                                      color: const Color(0xff6C6B6A)));
                            } else if (value == spots.length - 1) {
                              return Text(endTime,
                                  style: TextStyle(
                                      fontSize: 11.sp,
                                      color: const Color(0xff6C6B6A)));
                            }
                            return const SizedBox.shrink();
                          },
                        ),
                      ),
                    ),
                    gridData: FlGridData(
                      show: true,
                      drawHorizontalLine: true,
                      drawVerticalLine: false,
                      horizontalInterval: 50,
                      getDrawingHorizontalLine: (value) => FlLine(
                        color: const Color(0xFF5A5A5A),
                        dashArray: value == 100 ? [6, 3] : [3, 6],
                        strokeWidth: value == 100 ? 1.2 : 0.6,
                      ),
                    ),
                    lineBarsData: [
                      // 参考线（蓝色虚线弧线）- 模拟一夜好眠的心率曲线
                      LineChartBarData(
                        color: const Color(0xFF2F7BFF),
                        isCurved: true,
                        barWidth: 2,
                        dashArray: [5, 5],
                        spots: _generateGoodSleepCurve(spots.length),
                        dotData: const FlDotData(show: false),
                        belowBarData: BarAreaData(show: false),
                      ),
                      // 主线（橙色）
                      LineChartBarData(
                        color: const Color(0xFFE76234),
                        isCurved: true,
                        barWidth: 3,
                        spots: spots,
                        isStrokeCapRound: true,
                        dotData: const FlDotData(show: false),
                        belowBarData: BarAreaData(show: false),
                      ),
                    ],
                  ),
                ),
              ),
              // 右侧标签："一夜好眠曲线示例"
              Positioned(
                right: 12.w,
                top: 40.h,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Container(
                      width: 20.w,
                      height: 2.h,
                      decoration: BoxDecoration(
                        gradient: LinearGradient(
                          colors: [
                            const Color(0xFF2F7BFF),
                            const Color(0xFF2F7BFF).withOpacity(0),
                          ],
                        ),
                      ),
                    ),
                    SizedBox(height: 4.h),
                    Text(
                      '一夜好眠',
                      style: TextStyle(
                        fontSize: 11.sp,
                        color: const Color(0xFF2F7BFF),
                        height: 1.2,
                      ),
                    ),
                    Text(
                      '曲线示例',
                      style: TextStyle(
                        fontSize: 11.sp,
                        color: const Color(0xFF2F7BFF),
                        height: 1.2,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
          SizedBox(height: 12.h),
          // 最高和最低值
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
                decoration: BoxDecoration(
                  color: const Color(0xFF2F2B2C),
                  borderRadius: BorderRadius.circular(14.r),
                ),
                child: Text(
                  '最低${heartRateData.minValue} bpm',
                  style: TextStyle(
                    fontSize: 14.sp,
                    color: Colors.white.withOpacity(0.9),
                  ),
                ),
              ),
              SizedBox(width: 16.w),
              Container(
                padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
                decoration: BoxDecoration(
                  color: const Color(0xFF2F2B2C),
                  borderRadius: BorderRadius.circular(14.r),
                ),
                child: Text(
                  '最高${heartRateData.maxValue} bpm',
                  style: TextStyle(
                    fontSize: 14.sp,
                    color: Colors.white.withOpacity(0.9),
                  ),
                ),
              ),
            ],
          ),
        ],
      );
    });
  }

  /// 构建通用的指标柱状图（周/月视图）
  Widget _buildMetricBarChart(
    SleepMetricData? data,
    String title,
    String unit,
    MetricType type,
  ) {
    if (data == null || data.longSleepDates == null || data.longSleepDates!.isEmpty) {
      return Center(
        child: Padding(
          padding: EdgeInsets.symmetric(vertical: 40.h),
          child: Text(
            '--',
            style: TextStyle(
              fontSize: 32.sp,
              color: Colors.white.withOpacity(0.3),
            ),
          ),
        ),
      );
    }

    final dates = data.longSleepDates!;
    final validData = dates.where((date) {
      MetricRangeInfo? info;
      switch (type) {
        case MetricType.heartRate:
          info = date.longSleepRateInfo;
          break;
        case MetricType.hrv:
          info = date.longSleepHrvInfo;
          break;
        case MetricType.bloodOxygen:
          info = date.longSleepBoInfo;
          break;
      }
      return info != null && (info.maxValue > 0 || info.minValue > 0);
    }).toList();

    if (validData.isEmpty) {
      return Center(
        child: Padding(
          padding: EdgeInsets.symmetric(vertical: 40.h),
          child: Text(
            '--',
            style: TextStyle(
              fontSize: 32.sp,
              color: Colors.white.withOpacity(0.3),
            ),
          ),
        ),
      );
    }

    return Column(
      children: [
        // 平均值
        Padding(
          padding: EdgeInsets.symmetric(vertical: 12.h),
          child: Column(
            children: [
              _buildRichDuration('${data.average}$unit',
                  numberSize: 32.sp, unitSize: 14.sp),
              SizedBox(height: 4.h),
              Text(
                '平均值',
                style: TextStyle(
                  fontSize: 13.sp,
                  color: Colors.white.withOpacity(0.7),
                ),
              ),
            ],
          ),
        ),
        SizedBox(
          height: 220.h,
          child: BarChart(
            BarChartData(
              alignment: BarChartAlignment.spaceBetween,
              maxY: type == MetricType.bloodOxygen ? 100 : 120,
              titlesData: FlTitlesData(
                leftTitles: AxisTitles(
                  sideTitles: SideTitles(
                    showTitles: true,
                    interval: type == MetricType.bloodOxygen ? 25 : 30,
                    reservedSize: 32,
                    getTitlesWidget: (v, m) => Text(
                      v.toInt().toString(),
                      style: TextStyle(
                        fontSize: 11.sp,
                        color: const Color(0xff5A5A5A),
                      ),
                    ),
                  ),
                ),
                rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
                topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
                bottomTitles: AxisTitles(
                  sideTitles: SideTitles(
                    showTitles: true,
                    getTitlesWidget: (value, meta) {
                      final int i = value.toInt();
                      if (i < 0 || i >= dates.length) return const SizedBox.shrink();
                      
                      bool shouldDisplay = false;
                      if (currentTimeRange == TimeRange.week) {
                        shouldDisplay = true;
                      } else if (currentTimeRange == TimeRange.month) {
                        try {
                          final dayNum = int.parse(dates[i].dailyValue.split('/').last);
                          shouldDisplay = (dayNum == 1 || dayNum % 5 == 0);
                        } catch (e) {
                          shouldDisplay = (i == 0 || i == dates.length - 1);
                        }
                      }
                      
                      if (!shouldDisplay) return const SizedBox.shrink();
                      
                      return SideTitleWidget(
                        axisSide: meta.axisSide,
                        space: 6,
                        child: Text(
                          dates[i].dailyValue.split('/').last,
                          style: TextStyle(
                            fontSize: 12.sp,
                            color: const Color(0xff6C6B6A),
                          ),
                        ),
                      );
                    },
                    reservedSize: 22,
                  ),
                ),
              ),
              barTouchData: BarTouchData(enabled: false),
              borderData: FlBorderData(show: false),
              gridData: const FlGridData(show: false),
              barGroups: List.generate(dates.length, (index) {
                MetricRangeInfo? info;
                switch (type) {
                  case MetricType.heartRate:
                    info = dates[index].longSleepRateInfo;
                    break;
                  case MetricType.hrv:
                    info = dates[index].longSleepHrvInfo;
                    break;
                  case MetricType.bloodOxygen:
                    info = dates[index].longSleepBoInfo;
                    break;
                }

                if (info == null || (info.maxValue == 0 && info.minValue == 0)) {
                  return BarChartGroupData(x: index, barRods: []);
                }

                return BarChartGroupData(
                  x: index,
                  barRods: [
                    BarChartRodData(
                      fromY: info.minValue.toDouble(),
                      toY: info.maxValue.toDouble(),
                      color: const Color(0xFFE76234),
                      width: 16.w,
                      borderRadius: BorderRadius.vertical(top: Radius.circular(4.r)),
                    ),
                  ],
                );
              }),
            ),
          ),
        ),
      ],
    );
  }

  /// 平均心率变异性（带背景区域）
  Widget _buildAvgHrvSection() {
    return Obx(() {
      final hrvData = controller.state.sleepHrvData.value;
      final timeRange = currentTimeRange;

      // 周/月视图：显示柱状图
      if (timeRange == TimeRange.week || timeRange == TimeRange.month) {
        return _buildMetricBarChart(
          hrvData,
          '平均心率变异性',
          'ms',
          MetricType.hrv,
        );
      }

      // 日视图：显示折线图
      final hasData = hrvData != null && hrvData.dataList.isNotEmpty;

      if (!hasData) {
        return Center(
          child: Padding(
            padding: EdgeInsets.symmetric(vertical: 40.h),
            child: Text(
              '--',
              style: TextStyle(
                fontSize: 32.sp,
                color: Colors.white.withOpacity(0.3),
              ),
            ),
          ),
        );
      }

      // 构建数据点
      final List<FlSpot> spots = [];
      for (int i = 0; i < hrvData.dataList.length; i++) {
        spots.add(FlSpot(i.toDouble(), hrvData.dataList[i].value.toDouble()));
      }

      // 获取开始和结束时间
      final startTime = hrvData.dataList.first.key;
      final endTime = hrvData.dataList.last.key;

      return Column(
        children: [
          // 平均值和范围
          Padding(
            padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h),
            child: Row(
              children: [
                _buildValueRichText('${hrvData.average} ms平均值'),
                Spacer(),
                Text(
                  '基线范围: 35-75ms',
                  style: TextStyle(
                    fontSize: 12.sp,
                    color: const Color(0xff6C6B6A),
                  ),
                ),
              ],
            ),
          ),
          SizedBox(
            height: 220.h,
            child: LineChart(
              LineChartData(
                minY: 0,
                maxY: 120,
                borderData: FlBorderData(show: false),
                lineTouchData: const LineTouchData(enabled: false),
                titlesData: FlTitlesData(
                  leftTitles: AxisTitles(
                    sideTitles: SideTitles(
                      showTitles: true,
                      reservedSize: 32,
                      interval: 50,
                      getTitlesWidget: (value, meta) => Text(
                        value.toInt().toString(),
                        style: TextStyle(
                            fontSize: 11.sp, color: const Color(0xff6C6B6A)),
                      ),
                    ),
                  ),
                  rightTitles: const AxisTitles(
                      sideTitles: SideTitles(showTitles: false)),
                  topTitles: const AxisTitles(
                      sideTitles: SideTitles(showTitles: false)),
                  bottomTitles: AxisTitles(
                    sideTitles: SideTitles(
                      showTitles: true,
                      interval:
                          spots.length > 1 ? (spots.length - 1).toDouble() : 1,
                      getTitlesWidget: (value, meta) {
                        if (value == 0) {
                          return Text(startTime,
                              style: TextStyle(
                                  fontSize: 11.sp,
                                  color: const Color(0xff6C6B6A)));
                        } else if (value == spots.length - 1) {
                          return Text(endTime,
                              style: TextStyle(
                                  fontSize: 11.sp,
                                  color: const Color(0xff6C6B6A)));
                        }
                        return const SizedBox.shrink();
                      },
                    ),
                  ),
                ),
                gridData: FlGridData(
                  show: true,
                  drawHorizontalLine: true,
                  drawVerticalLine: false,
                  horizontalInterval: 50,
                  getDrawingHorizontalLine: (value) => FlLine(
                    color: const Color(0xFF5A5A5A),
                    dashArray: [6, 3],
                    strokeWidth: 0.6,
                  ),
                ),
                lineBarsData: [
                  LineChartBarData(
                    color: const Color(0xFFE76234),
                    isCurved: true,
                    barWidth: 3,
                    spots: spots,
                    isStrokeCapRound: true,
                    dotData: const FlDotData(show: false),
                    belowBarData: BarAreaData(
                      show: true,
                      gradient: LinearGradient(
                        begin: Alignment.topCenter,
                        end: Alignment.bottomCenter,
                        colors: [
                          const Color(0xFFE76234).withOpacity(0.35),
                          const Color(0xFFE76234).withOpacity(0.10),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
          SizedBox(height: 12.h),
          // 最高和最低值
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
                decoration: BoxDecoration(
                  color: const Color(0xFF2F2B2C),
                  borderRadius: BorderRadius.circular(14.r),
                ),
                child: Text(
                  '最低${hrvData.minValue}ms',
                  style: TextStyle(
                    fontSize: 14.sp,
                    color: Colors.white.withOpacity(0.9),
                  ),
                ),
              ),
              SizedBox(width: 16.w),
              Container(
                padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
                decoration: BoxDecoration(
                  color: const Color(0xFF2F2B2C),
                  borderRadius: BorderRadius.circular(14.r),
                ),
                child: Text(
                  '最高${hrvData.maxValue}ms',
                  style: TextStyle(
                    fontSize: 14.sp,
                    color: Colors.white.withOpacity(0.9),
                  ),
                ),
              ),
            ],
          ),
        ],
      );
    });
  }

  /// 血氧饱和度曲线
  Widget _buildBloodOxygenSection() {
    return Obx(() {
      final boData = controller.state.sleepBloodOxygenData.value;
      final timeRange = currentTimeRange;

      // 周/月视图：显示柱状图
      if (timeRange == TimeRange.week || timeRange == TimeRange.month) {
        return _buildMetricBarChart(
          boData,
          '血氧饱和度',
          '%',
          MetricType.bloodOxygen,
        );
      }

      // 日视图：显示折线图
      final hasData = boData != null && boData.dataList.isNotEmpty;

      if (!hasData) {
        return Center(
          child: Padding(
            padding: EdgeInsets.symmetric(vertical: 40.h),
            child: Text(
              '--',
              style: TextStyle(
                fontSize: 32.sp,
                color: Colors.white.withOpacity(0.3),
              ),
            ),
          ),
        );
      }

      // 构建数据点
      final List<FlSpot> spots = [];
      for (int i = 0; i < boData.dataList.length; i++) {
        spots.add(FlSpot(i.toDouble(), boData.dataList[i].value.toDouble()));
      }

      // 获取开始和结束时间
      final startTime = boData.dataList.first.key;
      final endTime = boData.dataList.last.key;

      return Column(
        children: [
          // 平均值和范围
          Padding(
            padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h),
            child: Row(
              children: [
                _buildValueRichText('${boData.average} %平均值'),
                Spacer(),
                Text(
                  '基线范围: >90',
                  style: TextStyle(
                    fontSize: 12.sp,
                    color: const Color(0xff6C6B6A),
                  ),
                ),
              ],
            ),
          ),
          SizedBox(
            height: 220.h,
            child: LineChart(
              LineChartData(
                minY: 0,
                maxY: 100,
                borderData: FlBorderData(show: false),
                lineTouchData: const LineTouchData(enabled: false),
                titlesData: FlTitlesData(
                  leftTitles: AxisTitles(
                    sideTitles: SideTitles(
                      showTitles: true,
                      reservedSize: 32,
                      interval: 50,
                      getTitlesWidget: (value, meta) => Text(
                        value.toInt().toString(),
                        style: TextStyle(
                            fontSize: 11.sp, color: const Color(0xff6C6B6A)),
                      ),
                    ),
                  ),
                  rightTitles: const AxisTitles(
                      sideTitles: SideTitles(showTitles: false)),
                  topTitles: const AxisTitles(
                      sideTitles: SideTitles(showTitles: false)),
                  bottomTitles: AxisTitles(
                    sideTitles: SideTitles(
                      showTitles: true,
                      interval:
                          spots.length > 1 ? (spots.length - 1).toDouble() : 1,
                      getTitlesWidget: (value, meta) {
                        if (value == 0) {
                          return Text(startTime,
                              style: TextStyle(
                                  fontSize: 11.sp,
                                  color: const Color(0xff6C6B6A)));
                        } else if (value == spots.length - 1) {
                          return Text(endTime,
                              style: TextStyle(
                                  fontSize: 11.sp,
                                  color: const Color(0xff6C6B6A)));
                        }
                        return const SizedBox.shrink();
                      },
                    ),
                  ),
                ),
                gridData: FlGridData(
                  show: true,
                  drawHorizontalLine: true,
                  drawVerticalLine: false,
                  horizontalInterval: 50,
                  getDrawingHorizontalLine: (value) => FlLine(
                    color: const Color(0xFF5A5A5A),
                    dashArray: [6, 3],
                    strokeWidth: 0.6,
                  ),
                ),
                lineBarsData: [
                  LineChartBarData(
                    color: const Color(0xFFE76234),
                    isCurved: true,
                    barWidth: 3,
                    spots: spots,
                    isStrokeCapRound: true,
                    dotData: const FlDotData(show: false),
                    belowBarData: BarAreaData(
                      show: true,
                      gradient: LinearGradient(
                        begin: Alignment.topCenter,
                        end: Alignment.bottomCenter,
                        colors: [
                          const Color(0xFFE76234).withOpacity(0.35),
                          const Color(0xFFE76234).withOpacity(0.10),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
          SizedBox(height: 12.h),
          // 最高和最低值
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
                decoration: BoxDecoration(
                  color: const Color(0xFF2F2B2C),
                  borderRadius: BorderRadius.circular(14.r),
                ),
                child: Text(
                  '最低${boData.minValue}%',
                  style: TextStyle(
                    fontSize: 14.sp,
                    color: Colors.white.withOpacity(0.9),
                  ),
                ),
              ),
              SizedBox(width: 16.w),
              Container(
                padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
                decoration: BoxDecoration(
                  color: const Color(0xFF2F2B2C),
                  borderRadius: BorderRadius.circular(14.r),
                ),
                child: Text(
                  '最高${boData.maxValue}%',
                  style: TextStyle(
                    fontSize: 14.sp,
                    color: Colors.white.withOpacity(0.9),
                  ),
                ),
              ),
            ],
          ),
        ],
      );
    });
  }

  /// 睡眠活动状态（分三种强度，使用不等高柱形）
  Widget _buildSleepActivitySection() {
    return Obx(() {
      final activityData = controller.state.sleepActivityData.value;
      final hasData = activityData != null;

      if (!hasData) {
        return Center(
          child: Padding(
            padding: EdgeInsets.symmetric(vertical: 40.h),
            child: Text(
              '--',
              style: TextStyle(
                fontSize: 32.sp,
                color: Colors.white.withOpacity(0.3),
              ),
            ),
          ),
        );
      }

      // 添加活动强度时间线图表
      return Column(
        children: [
          // 活动强度时间线
          _buildActivityTimeline(activityData),
          SizedBox(height: 32.h),
        ],
      );
    });
  }

  /// 构建活动强度时间线
  Widget _buildActivityTimeline(SleepActivityStatusData activityData) {
    return Column(
      children: [
        // 活动强度柱状图
        Container(
          height: 120.h,
          child: CustomPaint(
            painter: ActivityTimelinePainter(
              activityData: activityData,
            ),
            child: Container(),
          ),
        ),
        SizedBox(height: 8.h),
        // 入睡和清醒时间标注
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(
              '${activityData.sleepStartDate} ${activityData.sleepTime} 入睡',
              style: TextStyle(
                fontSize: 11.sp,
                color: Colors.white.withOpacity(0.7),
              ),
            ),
            Text(
              '${activityData.sleepEndDate} ${activityData.soberTime} 清醒',
              style: TextStyle(
                fontSize: 11.sp,
                color: Colors.white.withOpacity(0.7),
              ),
            ),
          ],
        ),
        SizedBox(height: 12.h),
        // 图例
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            _legendDot(Color(0xFF5B9BFF), '小幅活动'),
            _legendDot(Color(0xFFFFB366), '中幅活动'),
            _legendDot(Color(0xFFE76234), '频繁活动'),
          ],
        ),
      ],
    );
  }

  /// 近7日睡眠趋势柱状图
  Widget _buildActivityBarChart() {
    return Obx(() {
      final trendData = controller.state.sleepTrendData.value;

      // 四段堆叠：深睡(底)、浅睡(第二层)、快速眼动(第三层)、清醒(顶)
      const Color deepColor = Color(0xFF4B241A); // 深睡眠 - 深棕色
      const Color lightColor = Color(0xFFE76234); // 浅睡眠 - 红橙色
      const Color remColor = Color(0xFFFFC066); // 快速眼动 - 橙色
      const Color awakeColor = Color(0xFFE0E0E0); // 清醒 - 浅灰色
      const double between = 0.0; // 阶段之间没有边距

      BarChartGroupData generate(int x, double deep, double light, double rem, double awake) {
        return BarChartGroupData(
          x: x,
          groupVertically: true,
          barRods: [
            BarChartRodData(
                fromY: 0,
                toY: deep,
                color: deepColor,
                width: 16.w,
                borderRadius: BorderRadius.circular(4.r)),
            BarChartRodData(
                fromY: deep + between,
                toY: deep + between + light,
                color: lightColor,
                width: 16.w,
                borderRadius: BorderRadius.circular(4.r)),
            BarChartRodData(
                fromY: deep + between + light + between,
                toY: deep + between + light + between + rem,
                color: remColor,
                width: 16.w,
                borderRadius: BorderRadius.circular(4.r)),
            BarChartRodData(
                fromY: deep + between + light + between + rem + between,
                toY: deep + between + light + between + rem + between + awake,
                color: awakeColor,
                width: 16.w,
                borderRadius: BorderRadius.circular(4.r)),
          ],
        );
      }

      // 使用API返回的实际数据
      final List<BarChartGroupData> groups = [];
      final List<String> dates = [];
      final List<double> totalHeights = []; // 存储每个柱子的总高度用于连线

      if (trendData != null && trendData.chart.isNotEmpty) {
        // 使用API返回的数据
        for (int i = 0; i < trendData.chart.length; i++) {
          final trend = trendData.chart[i];
          
          // 解析日期并格式化显示
          try {
            final dateParts = trend.dailyValue.split('-');
            if (dateParts.length == 3) {
              final month = int.parse(dateParts[1]);
              final day = int.parse(dateParts[2]);
              dates.add('$month/$day');
            } else {
              dates.add(trend.dailyValue);
            }
          } catch (e) {
            dates.add(trend.dailyValue);
          }

          if (trend.trendList.length >= 4) {
            // trendList 顺序: [0]=awake, [1]=rem, [2]=light, [3]=deep
            final awakeHours = trend.trendList[0].value / 60.0;
            final remHours = trend.trendList[1].value / 60.0;
            final lightHours = trend.trendList[2].value / 60.0;
            final deepHours = trend.trendList[3].value / 60.0;
            
            // 检查是否所有值都为0
            final hasData = awakeHours > 0 || remHours > 0 || lightHours > 0 || deepHours > 0;
            
            if (hasData) {
              final totalHeight = deepHours + lightHours + remHours + awakeHours + (between * 3);
              totalHeights.add(totalHeight);
              
              groups.add(generate(
                i,
                deepHours,
                lightHours,
                remHours,
                awakeHours,
              ));
            } else {
              // 所有值都为0，不显示柱状图
              totalHeights.add(0);
              groups.add(BarChartGroupData(x: i, barRods: []));
            }
          } else {
            // 无数据，显示空柱
            totalHeights.add(0);
            groups.add(BarChartGroupData(x: i, barRods: []));
          }
        }
      } else {
        // 如果没有数据，显示空图表
        for (int i = 0; i < 7; i++) {
          dates.add('--');
          totalHeights.add(0);
          groups.add(generate(i, 0, 0, 0, 0));
        }
      }

      Widget bottomTitle(double value, TitleMeta meta) {
        final int i = value.toInt();
        if (i < 0 || i >= dates.length) return const SizedBox.shrink();
        return SideTitleWidget(
            axisSide: meta.axisSide,
            space: 6,
            child: Text(dates[i],
                style: TextStyle(
                    fontSize: 12.sp, color: const Color(0xff6C6B6A))));
      }

      // 获取平均睡眠时间
      final averageSleepTime = trendData?.sleepDuration ?? '--';

      return Column(children: [
        // 显示平均睡眠时间 - 上下布局
        Padding(
          padding: EdgeInsets.symmetric(vertical: 12.h),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              _buildRichDuration(averageSleepTime,
                  numberSize: 32.sp, unitSize: 14.sp),
              SizedBox(height: 4.h),
              Text(
                '平均睡眠时间',
                style: TextStyle(
                  fontSize: 13.sp,
                  color: Colors.white.withOpacity(0.7),
                ),
              ),
            ],
          ),
        ),
        SizedBox(
          height: 220.h,
          child: Stack(
            children: [
              // 连接线层
              CustomPaint(
                size: Size.infinite,
                painter: SleepTrendLinePainter(
                  totalHeights: totalHeights,
                  dataCount: groups.length,
                  maxY: 12,
                ),
              ),
              // 柱状图层
              BarChart(
                BarChartData(
                  alignment: BarChartAlignment.spaceBetween,
                  maxY: 12,
                  titlesData: FlTitlesData(
                    leftTitles: AxisTitles(
                      sideTitles: SideTitles(
                        showTitles: true,
                        interval: 1,
                        reservedSize: 60,
                        getTitlesWidget: (v, m) {
                          final labels = ['', '深睡眠', '', '', '浅睡眠', '', '', '快速眼动', '', '', '清醒', ''];
                          final index = v.toInt();
                          if (index >= 0 && index < labels.length && labels[index].isNotEmpty) {
                            return Text(labels[index],
                                style: TextStyle(
                                    fontSize: 11.sp,
                                    color: const Color(0xff5A5A5A)));
                          }
                          return const SizedBox.shrink();
                        },
                      ),
                    ),
                    rightTitles:
                        const AxisTitles(sideTitles: SideTitles(showTitles: false)),
                    topTitles:
                        const AxisTitles(sideTitles: SideTitles(showTitles: false)),
                    bottomTitles: AxisTitles(
                        sideTitles: SideTitles(
                            showTitles: true,
                            getTitlesWidget: bottomTitle,
                            reservedSize: 22)),
                  ),
                  barTouchData: BarTouchData(enabled: false),
                  borderData: FlBorderData(show: false),
                  gridData: const FlGridData(show: false),
                  barGroups: groups,
                ),
              ),
            ],
          ),
        ),
      ]);
    });
  }

  Widget _legendDot(Color color, String text) {
    return Row(
      children: [
        Container(
            width: 10.w,
            height: 10.w,
            decoration: BoxDecoration(color: color, shape: BoxShape.circle)),
        SizedBox(width: 6.w),
        Text(text,
            style: TextStyle(fontSize: 12.sp, color: const Color(0xff908E8D))),
      ],
    );
  }

  /// 生成"一夜好眠"的理想心率曲线
  /// 模拟一个平滑的弧线，从入睡时较高，逐渐降低到深睡眠，然后在清醒前逐渐升高
  List<FlSpot> _generateGoodSleepCurve(int dataPointCount) {
    final List<FlSpot> curve = [];

    for (int i = 0; i < dataPointCount; i++) {
      final double x = i.toDouble();
      final double progress = i / (dataPointCount - 1); // 0.0 到 1.0

      // 使用正弦波的变形创建一个自然的弧线
      // 开始时心率约60，中间降到约45，结束时回到约55
      double y;
      if (progress < 0.3) {
        // 入睡阶段：从60逐渐降到50
        y = 60 - (progress / 0.3) * 10;
      } else if (progress < 0.7) {
        // 深睡阶段：保持在45-50之间的低心率
        final deepProgress = (progress - 0.3) / 0.4;
        y = 50 - 5 * (1 - (deepProgress - 0.5).abs() * 2);
      } else {
        // 清醒前阶段：从50逐渐升到55
        final wakeProgress = (progress - 0.7) / 0.3;
        y = 50 + wakeProgress * 5;
      }

      curve.add(FlSpot(x, y));
    }

    return curve;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: _buildView(),
    );
  }
}

class ActivityBar {
  final int h;
  final Color color;
  ActivityBar({required this.h, required this.color});
}

class TimeTicksPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {}

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

/// 睡眠阶段时间轴绘制器
class SleepStageTimelinePainter extends CustomPainter {
  final Map<String, List<SleepStageSegment>> sleepMaps;
  final String startDate;
  final String endDate;

  SleepStageTimelinePainter({
    required this.sleepMaps,
    required this.startDate,
    required this.endDate,
  });

  @override
  void paint(Canvas canvas, Size size) {
    // 睡眠阶段定义
    const Map<String, Color> stageColors = {
      'awake': Color(0xFFE0E0E0), // 清醒 - 浅灰色
      'rem': Color(0xFFFFB366), // 快速眼动 - 浅橙色
      'light': Color(0xFFFF8C42), // 浅睡眠 - 橙色
      'deep': Color(0xFF4B241A), // 深睡眠 - 深棕色
    };

    // 睡眠阶段标签
    const List<String> stageLabels = ['清醒', '快速眼动', '浅睡眠', '深睡眠'];

    // 从真实数据构建睡眠阶段列表
    final List<Map<String, dynamic>> sleepData = [];

    // 解析开始和结束时间
    final startDateTime = DateTime.parse(startDate);
    final endDateTime = DateTime.parse(endDate);
    final double totalDuration =
        endDateTime.difference(startDateTime).inMinutes.toDouble();

    // 遍历 maps 中的所有阶段
    sleepMaps.forEach((key, segments) {
      for (var segment in segments) {
        // 解析时间字符串 "HH:mm"
        final startParts = segment.startTime.split(':');
        final startHour = int.parse(startParts[0]);
        final startMinute = int.parse(startParts[1]);

        // 创建片段开始时间（可能跨天）
        var segmentStart = DateTime(startDateTime.year, startDateTime.month,
            startDateTime.day, startHour, startMinute);

        // 如果片段时间早于睡眠开始时间，说明跨天了，加一天
        if (segmentStart.isBefore(startDateTime)) {
          segmentStart = segmentStart.add(Duration(days: 1));
        }

        // 计算从睡眠开始到这个片段开始的分钟数
        final minutesFromStart =
            segmentStart.difference(startDateTime).inMinutes;

        // 确定阶段类型
        String stage;
        switch (segment.sleepType) {
          case 0:
            stage = 'awake';
            break;
          case 1:
            stage = 'light';
            break;
          case 2:
            stage = 'deep';
            break;
          case 3:
            stage = 'rem';
            break;
          default:
            stage = 'awake';
        }

        sleepData.add({
          'stage': stage,
          'duration': segment.totalTime,
          'startTime': minutesFromStart,
        });
      }
    });

    // 按开始时间排序
    sleepData.sort(
        (a, b) => (a['startTime'] as int).compareTo(b['startTime'] as int));
    final double stageHeight = size.height / 4; // 每个睡眠阶段的高度
    final double chartWidth = size.width;
    final double labelWidth = 60; // 为左边标签预留的宽度

    // 绘制横向虚线网格线
    final Paint gridPaint = Paint()
      ..color = Colors.white.withOpacity(0.2)
      ..strokeWidth = 0.5;

    // 绘制水平虚线网格线（从标签区域右边开始）
    for (int i = 0; i <= 4; i++) {
      final double y = i * stageHeight;
      _drawDashedLine(
        canvas,
        Offset(labelWidth, y),
        Offset(chartWidth, y),
        gridPaint,
        dashWidth: 4,
        dashSpace: 2,
      );
    }

    // 绘制睡眠阶段标签
    final TextPainter textPainter = TextPainter(
      textDirection: TextDirection.ltr,
      textAlign: TextAlign.left,
    );

    for (int i = 0; i < stageLabels.length; i++) {
      textPainter.text = TextSpan(
        text: stageLabels[i],
        style: TextStyle(
          color: Colors.white.withOpacity(0.7),
          fontSize: 12,
        ),
      );
      textPainter.layout();
      textPainter.paint(
        canvas,
        Offset(8, i * stageHeight + stageHeight / 2 - textPainter.height / 2),
      );
    }

    // 绘制睡眠阶段数据
    final Paint stagePaint = Paint();

    for (final data in sleepData) {
      final String stage = data['stage'] as String;
      final int duration = data['duration'] as int;
      final int startTime = data['startTime'] as int;

      final Color color = stageColors[stage]!;
      stagePaint.color = color;

      // 计算位置（从标签区域右边开始）
      final double x =
          labelWidth + (startTime / totalDuration) * (chartWidth - labelWidth);
      final double width =
          (duration / totalDuration) * (chartWidth - labelWidth);

      // 确定Y位置 - 根据睡眠阶段类型
      double y;
      switch (stage) {
        case 'awake':
          y = 0; // 顶部
          break;
        case 'rem':
          y = stageHeight; // 第二层
          break;
        case 'light':
          y = stageHeight * 2; // 第三层
          break;
        case 'deep':
          y = stageHeight * 3; // 底部
          break;
        default:
          y = 0;
      }

      // 绘制睡眠阶段块
      final Rect rect = Rect.fromLTWH(x, y, width, stageHeight);
      canvas.drawRect(rect, stagePaint);
    }
  }

  /// 绘制虚线
  void _drawDashedLine(Canvas canvas, Offset start, Offset end, Paint paint,
      {double dashWidth = 5, double dashSpace = 3}) {
    final double distance = (end - start).distance;
    final int dashCount = (distance / (dashWidth + dashSpace)).floor();
    final Offset direction = (end - start) / distance;

    for (int i = 0; i < dashCount; i++) {
      final Offset dashStart =
          start + direction * (dashWidth + dashSpace) * i.toDouble();
      final Offset dashEnd = start +
          direction * ((dashWidth + dashSpace) * i.toDouble() + dashWidth);
      canvas.drawLine(dashStart, dashEnd, paint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

/// 活动强度时间线绘制器
class ActivityTimelinePainter extends CustomPainter {
  final SleepActivityStatusData activityData;

  ActivityTimelinePainter({required this.activityData});

  @override
  void paint(Canvas canvas, Size size) {
    final chartWidth = size.width;
    final chartHeight = size.height;

    // 收集所有活动数据点
    final List<Map<String, dynamic>> allActivityPoints = [];

    // 遍历所有活动类型
    for (var activityGroup in activityData.activityStatusList) {
      final activityType = activityGroup.activityType;

      for (var point in activityGroup.activityStatusList) {
        allActivityPoints.add({
          'time': point.key,
          'value': point.value,
          'type': activityType,
        });
      }
    }

    if (allActivityPoints.isEmpty) {
      return;
    }

    // 按时间排序
    allActivityPoints.sort((a, b) => (a['time'] as String).compareTo(b['time'] as String));

    // 找出最大 value 用于归一化高度
    int maxValue = 0;
    for (var point in allActivityPoints) {
      final value = point['value'] as int;
      if (value > maxValue) {
        maxValue = value;
      }
    }

    // 绘制活动柱状图
    final Paint barPaint = Paint()..style = PaintingStyle.fill;

    // 计算柱子宽度 - 更细的柱子
    final int dataCount = allActivityPoints.length;
    final double barWidth = 4.0; // 固定细柱宽度
    final double spacing = (chartWidth - (barWidth * dataCount)) / (dataCount + 1); // 动态计算间距

    // 中心线位置
    final double centerY = chartHeight / 2;

    for (int i = 0; i < allActivityPoints.length; i++) {
      final point = allActivityPoints[i];
      final String activityType = point['type'] as String;
      final int value = point['value'] as int;

      // 根据活动类型确定颜色
      Color color;
      switch (activityType) {
        case '小幅活动':
          color = Color(0xFF5B9BFF);
          break;
        case '中幅活动':
          color = Color(0xFFFFB366);
          break;
        case '频繁活动':
          color = Color(0xFFE76234);
          break;
        default:
          color = Color(0xFF5B9BFF);
      }

      barPaint.color = color;

      // 根据 value 计算高度（归一化到 chartHeight 的 20%-60% 范围，整体更短）
      final double normalizedHeight = maxValue > 0 
          ? (value / maxValue) * chartHeight * 0.4 + chartHeight * 0.2
          : chartHeight * 0.2;
      
      final double barHeight = normalizedHeight.clamp(chartHeight * 0.2, chartHeight * 0.6);

      // 计算柱子位置 - 以中心线对齐
      final x = spacing + i * (barWidth + spacing);
      final y = centerY - barHeight / 2; // 中心对齐

      // 绘制圆角矩形柱子（更圆润的圆角）
      final rect = RRect.fromRectAndRadius(
        Rect.fromLTWH(x, y, barWidth, barHeight),
        Radius.circular(barWidth / 2), // 圆角半径为柱宽的一半，形成圆柱效果
      );
      canvas.drawRRect(rect, barPaint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

/// 指标类型枚举
enum MetricType {
  heartRate, // 心率
  hrv, // 心率变异性
  bloodOxygen, // 血氧
}

class _StageData {
  final String label;
  final String ref;
  final String time;
  final String percent;
  final Color color;
  final String? rateValue; // 评价值：偏少/适中/偏多
  
  double get percentValue {
    final String digits = percent.replaceAll('%', '');
    return double.tryParse(digits) ?? 0;
  }

  _StageData({
    required this.label,
    required this.ref,
    required this.time,
    required this.percent,
    required this.color,
    this.rateValue,
  });
}

/// 睡眠趋势连接线绘制器
class SleepTrendLinePainter extends CustomPainter {
  final List<double> totalHeights;
  final int dataCount;
  final double maxY;

  SleepTrendLinePainter({
    required this.totalHeights,
    required this.dataCount,
    required this.maxY,
  });

  @override
  void paint(Canvas canvas, Size size) {
    if (totalHeights.length < 2) return;

    // 计算左侧标签宽度（与 BarChart 的 reservedSize 对应）
    const double leftPadding = 60.0; // 增加左侧偏移量以对齐柱状图
    final double chartWidth = size.width - leftPadding;
    final double chartHeight = size.height - 22.0; // 减去底部标题高度

    // 计算每个柱子的中心位置
    final double barSpacing = chartWidth / dataCount;

    // 找到所有有数据的点
    final List<MapEntry<int, double>> validPoints = [];
    for (int i = 0; i < totalHeights.length; i++) {
      if (totalHeights[i] > 0) {
        validPoints.add(MapEntry(i, totalHeights[i]));
      }
    }

    // 为每个阶段绘制连接线
    // 阶段颜色定义
    final List<Color> stageColors = [
      const Color(0xFFE0E0E0), // 清醒 - 顶部
      const Color(0xFFFFC066), // 快速眼动
      const Color(0xFFE76234), // 浅睡眠
      const Color(0xFF4B241A), // 深睡眠 - 底部
    ];

    // 为每个阶段绘制连接线（从上到下）
    for (int stageIndex = 0; stageIndex < 4; stageIndex++) {
      final Paint dashedLinePaint = Paint()
        ..color = stageColors[stageIndex].withOpacity(0.6)
        ..strokeWidth = 2.0
        ..style = PaintingStyle.stroke;

      // 绘制该阶段的连接线（连接所有有数据的点，跨越没有数据的点）
      int? lastValidIndex;
      for (int i = 0; i < totalHeights.length; i++) {
        if (totalHeights[i] > 0) {
          if (lastValidIndex != null) {
            // 连接上一个有数据的点和当前点
            final double height1 = totalHeights[lastValidIndex];
            final double height2 = totalHeights[i];

            final double x1 = leftPadding + (lastValidIndex + 0.5) * barSpacing;
            final double x2 = leftPadding + (i + 0.5) * barSpacing;

            // 根据阶段计算不同的 Y 坐标
            // 每个阶段占总高度的 1/4
            final double stageHeight1 = height1 * (4 - stageIndex) / 4;
            final double stageHeight2 = height2 * (4 - stageIndex) / 4;

            final double y1 = chartHeight - (stageHeight1 / maxY) * chartHeight;
            final double y2 = chartHeight - (stageHeight2 / maxY) * chartHeight;

            // 绘制虚线连接
            _drawDashedLine(
              canvas,
              Offset(x1, y1),
              Offset(x2, y2),
              dashedLinePaint,
              dashWidth: 4,
              dashSpace: 3,
            );
          }
          lastValidIndex = i;
        }
      }
    }
  }

  /// 绘制虚线（改进版，消除缝隙）
  void _drawDashedLine(Canvas canvas, Offset start, Offset end, Paint paint,
      {double dashWidth = 5, double dashSpace = 3}) {
    final double distance = (end - start).distance;
    if (distance == 0) return;
    
    final Offset direction = (end - start) / distance;
    double currentDistance = 0;

    while (currentDistance < distance) {
      final Offset dashStart = start + direction * currentDistance;
      final double remainingDistance = distance - currentDistance;
      final double actualDashWidth = remainingDistance < dashWidth ? remainingDistance : dashWidth;
      final Offset dashEnd = start + direction * (currentDistance + actualDashWidth);
      
      canvas.drawLine(dashStart, dashEnd, paint);
      currentDistance += dashWidth + dashSpace;
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}


/// 小睡柱状图绘制器（周/月视图）
class NapChartPainter extends CustomPainter {
  final ShortSleepData napData;
  final TimeRange timeRange;

  NapChartPainter({
    required this.napData,
    required this.timeRange,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final chartWidth = size.width;
    final chartHeight = size.height;

    // 科学补觉区间：13:00-15:00（Y轴位置）
    const double recommendStart = 13.0; // 13:00
    const double recommendEnd = 15.0;   // 15:00
    const double dayHours = 24.0;

    // 计算科学补觉区间的Y轴位置（从上到下）
    final double recommendStartY = (recommendStart / dayHours) * chartHeight;
    final double recommendHeight = ((recommendEnd - recommendStart) / dayHours) * chartHeight;

    // 绘制科学补觉区间背景（横向蓝色条）
    final Paint recommendPaint = Paint()
      ..color = const Color(0xFF2F7BFF).withOpacity(0.15)
      ..style = PaintingStyle.fill;

    canvas.drawRect(
      Rect.fromLTWH(0, recommendStartY, chartWidth, recommendHeight),
      recommendPaint,
    );

    // 绘制科学补觉区间边框（虚线）
    final Paint borderPaint = Paint()
      ..color = const Color(0xFF2F7BFF)
      ..strokeWidth = 1.5
      ..style = PaintingStyle.stroke;

    _drawDashedLine(
      canvas,
      Offset(0, recommendStartY),
      Offset(chartWidth, recommendStartY),
      borderPaint,
      dashWidth: 4,
      dashSpace: 3,
    );
    _drawDashedLine(
      canvas,
      Offset(0, recommendStartY + recommendHeight),
      Offset(chartWidth, recommendStartY + recommendHeight),
      borderPaint,
      dashWidth: 4,
      dashSpace: 3,
    );

    // 绘制小睡柱状图
    final Paint napPaint = Paint()
      ..color = const Color(0xFFE76234)
      ..style = PaintingStyle.fill;

    final int dataCount = napData.shortSleepDates.length;
    if (dataCount == 0) return;

    final double barSpacing = chartWidth / (dataCount + 1);
    final double barWidth = barSpacing * 0.5;

    for (int i = 0; i < napData.shortSleepDates.length; i++) {
      final napDate = napData.shortSleepDates[i];
      
      if (napDate.shortSleepTimes == null || napDate.shortSleepTimes!.isEmpty) {
        continue;
      }

      // 计算该日所有小睡时间段
      for (var napTime in napDate.shortSleepTimes!) {
        try {
          final startParts = napTime.startDate.split(':');
          final endParts = napTime.endDate.split(':');
          
          if (startParts.length >= 2 && endParts.length >= 2) {
            final double startHour = double.parse(startParts[0]) + double.parse(startParts[1]) / 60.0;
            final double endHour = double.parse(endParts[0]) + double.parse(endParts[1]) / 60.0;
            
            // 计算柱子的X位置（横向）
            final double x = barSpacing * (i + 1) - barWidth / 2;
            
            // 计算柱子的Y位置和高度（纵向，从上到下）
            final double startY = (startHour / dayHours) * chartHeight;
            final double endY = (endHour / dayHours) * chartHeight;
            final double barHeight = (endY - startY).abs();

            // 绘制圆角矩形柱子（横向短柱）
            final rect = RRect.fromRectAndRadius(
              Rect.fromLTWH(x, startY, barWidth, barHeight),
              Radius.circular(barWidth / 2),
            );
            canvas.drawRRect(rect, napPaint);
          }
        } catch (e) {
          print('解析小睡时间失败: $e');
        }
      }
    }
  }

  /// 绘制虚线
  void _drawDashedLine(Canvas canvas, Offset start, Offset end, Paint paint,
      {double dashWidth = 5, double dashSpace = 3}) {
    final double distance = (end - start).distance;
    if (distance == 0) return;
    
    final Offset direction = (end - start) / distance;
    double currentDistance = 0;

    while (currentDistance < distance) {
      final Offset dashStart = start + direction * currentDistance;
      final double remainingDistance = distance - currentDistance;
      final double actualDashWidth = remainingDistance < dashWidth ? remainingDistance : dashWidth;
      final Offset dashEnd = start + direction * (currentDistance + actualDashWidth);
      
      canvas.drawLine(dashStart, dashEnd, paint);
      currentDistance += dashWidth + dashSpace;
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
